package com.dev.module_zqc_sleep.utils

import android.content.Context
import android.net.Uri
import android.os.Build
import android.os.Environment
import android.provider.MediaStore
import com.dev.module_zqc_sleep.mvi.model.MediaInfo
import com.dev.module_zqc_sleep.mvi.model.MediaType
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.flatMapMerge
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.flowOn
import java.text.SimpleDateFormat
import java.util.Date
import java.util.Locale

object ScanMediaUtils {

    @OptIn(ExperimentalCoroutinesApi::class)
    fun queryLocalMediaFlow(context: Context, vararg mediaTypes: MediaType): Flow<MediaInfo> =
        flowOf(*mediaTypes).flatMapMerge(mediaTypes.size) { mediaType ->
            flow {
                val uri: Uri = when (mediaType) {
                    MediaType.IMAGE -> MediaStore.Images.Media.EXTERNAL_CONTENT_URI
                    MediaType.VIDEO -> MediaStore.Video.Media.EXTERNAL_CONTENT_URI
                    MediaType.AUDIO -> MediaStore.Audio.Media.EXTERNAL_CONTENT_URI
                }

                val projection = mutableListOf(
                    MediaStore.MediaColumns._ID,
                    MediaStore.MediaColumns.DISPLAY_NAME,
                    MediaStore.MediaColumns.DATE_ADDED,
                    MediaStore.MediaColumns.SIZE
                )

                // API 29及以上的设备，使用 RELATIVE_PATH 和 IS_PENDING
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
                    projection.add(MediaStore.MediaColumns.RELATIVE_PATH)
                    projection.add(MediaStore.MediaColumns.IS_PENDING)
                } else {
                    // API 29以下使用DATA
                    projection.add(MediaStore.MediaColumns.DATA)
                }

                val selectionStringBuilder = StringBuilder("${MediaStore.MediaColumns.SIZE} >= ?")
                val selectionArgsList = mutableListOf("1024") // 设置最小文件大小为1KB

                // API 29及以上的设备，添加IS_PENDING条件
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
                    selectionStringBuilder.append(" AND ${MediaStore.MediaColumns.IS_PENDING} = 0")
                }

                val sortOrder = "${MediaStore.MediaColumns.DATE_ADDED} DESC"

                context.contentResolver.query(
                    uri,
                    projection.toTypedArray(),
                    selectionStringBuilder.toString(),
                    selectionArgsList.toTypedArray(),
                    sortOrder
                )?.use { cursor ->
                        val idColumn = cursor.getColumnIndexOrThrow(MediaStore.MediaColumns._ID)
                        val nameColumn = cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.DISPLAY_NAME)
                        val timeColumn = cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.DATE_ADDED)
                        val sizeColumn = cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.SIZE)
                        val displayNameColumn = cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.DISPLAY_NAME)

                        val fileRelativePath = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
                            cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.RELATIVE_PATH)
                        } else {
                            cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.DATA)
                        }

                        while (cursor.moveToNext()) {
                            val id = cursor.getLong(idColumn)
                            val name = cursor.getString(nameColumn)
                            val timeInSeconds = cursor.getLong(timeColumn)
                            val size = cursor.getLong(sizeColumn)

                            val mediaPath = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
                                val relativePath = cursor.getString(fileRelativePath)
                                val displayName = cursor.getString(displayNameColumn)
                                "${Environment.getExternalStorageDirectory()}/${relativePath}${displayName}"
                            } else {
                                cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.DATA))
                            }

                            val dateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault())
                            val formattedTime = dateFormat.format(Date(timeInSeconds * 1000))
                            val formattedSize = formatFileSize(size)

                            val mediaInfo = MediaInfo(id, mediaPath, name, formattedTime, formattedSize, mediaType)
                            emit(mediaInfo)
                        }
                    }
            }
        }.flowOn(Dispatchers.IO).distinctUntilChanged()

    /**
     * 格式化文件大小
     */
    private fun formatFileSize(size: Long): String {
        val kiloByte: Long = 1024
        val megaByte = kiloByte * 1024
        val gigaByte = megaByte * 1024
        val teraBytes = gigaByte * 1024

        return when {
            size < kiloByte -> "${size}B"
            size < megaByte -> "${size / kiloByte}KB"
            size < gigaByte -> "${String.format(Locale.ROOT, "%.2f", size / megaByte.toDouble())}MB"
            size < teraBytes -> "${String.format(Locale.ROOT, "%.2f", size / gigaByte.toDouble())}GB"
            else -> "${String.format(Locale.ROOT, "%.2f", size / teraBytes.toDouble())}TB"
        }
    }

}